﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.GData.Calendar;
using Google.GData.Extensions;
using Google.GData.Client;
using System.Collections;

namespace GoogleAppsTools
{
    /// <summary>
    /// A collection of methods that together access the google servers.  Each one is used by the one below it, and the final one is called in GoogleCalendar_Shown method.  
    /// EncryptionClass is used to decrypt the username and password in Properties.Settings.
    /// </summary>
    public class CalendarHelper
    {
        public string ApplicationName { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        public static CalendarService GetService(string applicationName, string userName, string password)
        {
            CalendarService service = new CalendarService(applicationName);
            service.setUserCredentials(userName, password);
            return service;
        }

        public static IEnumerable<EventEntry> GetAllEvents(CalendarService service, DateTime? startData)
        {
            //create the dates/times to check between.  Starts at either now or the beginning of the day, depending on the setting and finishes at the last second of the day.
            //creating the endOfDay value like this stops the servers returning events that will happen tomorrow.
            DateTime beginningOfDay;
            DateTime endOfDay = Convert.ToDateTime(DateTime.Now.ToLongDateString() + " 23:59:59");

            if (Properties.Settings.Default.ShowPastEvents)
                beginningOfDay = Convert.ToDateTime(DateTime.Now.ToLongDateString() + " 00:00:00");
            else
                beginningOfDay = DateTime.Now;

            // Create the query object:
            EventQuery query = new EventQuery();
            query.Uri = new Uri("http://www.google.com/calendar/feeds/" + service.Credentials.Username + "/private/full");
            query.StartTime = beginningOfDay;
            query.EndTime = endOfDay;
            // Tell the service to query:
            EventFeed calFeed = service.Query(query);
            return calFeed.Entries.Cast<EventEntry>();
        }

        public static void AddEvent(CalendarService service, string title, string contents, string location, DateTime startTime, DateTime endTime, bool allDay)
        {
            EventEntry entry = new EventEntry();

            // Set the title and content of the entry.
            entry.Title.Text = title;
            entry.Content.Content = contents;

            // Set a location for the event.
            Where eventLocation = new Where();
            eventLocation.ValueString = location;
            entry.Locations.Add(eventLocation);

            When eventTime = new When(startTime, endTime, allDay);
            entry.Times.Add(eventTime);

            Uri postUri = new Uri
            ("http://www.google.com/calendar/feeds/default/private/full");

            // Send the request and receive the response:
            AtomEntry insertedEntry = service.Insert(postUri, entry);
        }  

    }

    public interface ISyncDataSource<T> where T : IEquatable<T>
    {
        string Id { get; }
        IEnumerable<T> GetItemHeaders(DateTime? lastSyncTime);
        void LoadItemContents(IEnumerable<T> items);
        void WriteItem(GenericEvent item);
    }

    public class GoogleEventsSyncDataSource : ISyncDataSource<GenericEvent>
    {
        CalendarService service;

        public GoogleEventsSyncDataSource()
        {
            service = CalendarHelper.GetService("MyCalendar", EncryptionClass.ToInsecureString(EncryptionClass.DecryptString(Properties.Settings.Default.username)), EncryptionClass.ToInsecureString(EncryptionClass.DecryptString(Properties.Settings.Default.password)));
        }

        #region ISyncDataSource<GenericEvent> Members

        public string Id
        {
            get { return "Google Calander Sync Data Source"; }
        }

        public IEnumerable<GenericEvent> GetItemHeaders(DateTime? lastSyncTime)
        {
            var googleEvents = CalendarHelper.GetAllEvents(service, lastSyncTime);
            List<GenericEvent> genericEvents = new List<GenericEvent>();
            foreach (var googleEvent in googleEvents)
            {
                GenericEvent genericEvent = new GenericEvent();
                genericEvent.Title = googleEvent.Title.Text;
                genericEvent.Contents = googleEvent.Content.Content;
                genericEvent.Location = googleEvent.Locations.First().ValueString;
                genericEvent.StartTime = googleEvent.Times.First().StartTime;
                genericEvent.EndTime = googleEvent.Times.First().EndTime;
                genericEvents.Add(genericEvent);
            }
            return genericEvents;
        }

        public void LoadItemContents(IEnumerable<GenericEvent> items)
        {
            //Nothing to load here
        }

        public void WriteItem(GenericEvent item)
        {
                CalendarHelper.AddEvent(service, item.Title, item.Contents, item.Location, item.StartTime, item.EndTime, item.AllDay);
        }

        #endregion
    }

    public class GenericEvent : IEquatable<GenericEvent>
    {
        public string Title { get; set; }
        public string Contents { get; set; }
        public string Location { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }
        public bool AllDay { get; set; }
        public string Link { get; set; }

        #region IEquatable<GenericEvent> Members

        public bool Equals(GenericEvent other)
        {
            //Compare all fields to check equality
            if (this.Title == other.Title &&
                this.Contents == other.Contents &&
                this.Location == other.Location &&
                this.StartTime == other.StartTime &&
                this.EndTime == other.EndTime)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion
    }

    public class SyncManager<T> where T : IEquatable<T>
    {
        public string Name { get; set; }
        public ISyncDataSource<T> Source1 { get; set; }



        public IEnumerable<T> Synchronize(DateTime? lastSyncTime)
        {
            try
            {
                IEnumerable<T> list = Source1.GetItemHeaders(lastSyncTime).ToList();
                return list;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

    public class SyncService
    {

        SyncManager<GenericEvent> eventManager = new SyncManager<GenericEvent>();
        public string LastUpdateDate;
        public SyncService()
        {
            //Initialize Event Manager
            eventManager.Name = "..Event Synchronizer";
            eventManager.Source1 = new GoogleEventsSyncDataSource();
        }

        public List<GenericEvent> SynchronizeEvents()
        {
            List<GenericEvent> genericEvents = eventManager.Synchronize(DateTime.Now).ToList();
            return genericEvents;
        }


    }





}
